﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Jiuyong.Models;
using System.Xml.Linq;
using System.ComponentModel.DataAnnotations;
using System.IO;

namespace Jiuyong
{
	namespace Views
	{
		/// <summary>
		/// CodingModelsPage.xaml 的交互逻辑
		/// </summary>
		public partial class CodingModelsPage : Page
		{
			public CodingModelsPage()
			{
				InitializeComponent();
				this.Loaded += new RoutedEventHandler(CodingModelsPage_Loaded);
			}

			ViewModels.CodingModelsPageViewModel ViewModel
			{
				get
				{
					return DataContext as ViewModels.CodingModelsPageViewModel;
				}
			}

			void CodingModelsPage_Loaded(object sender, RoutedEventArgs e)
			{
				CommandBindings.AddRange(new CommandBindingCollection()
				{
					new CommandBinding(ApplicationCommands.Open, ViewModel.Subcommands)
					,
					new CommandBinding(ApplicationCommands.New,ViewModel.Subcommands)
					,
					new CommandBinding(MediaCommands.Play,ViewModel.CodingModels)
					,
					new CommandBinding(ApplicationCommands.Save,ViewModel.SaveSetting)
					,
					new CommandBinding(ApplicationCommands.Delete,ViewModel.ClearOutput)
					//,
					//new CommandBinding(ApplicationCommands.Properties,ViewModel.Subcommands)
					,
					new CommandBinding(ApplicationCommands.Properties,ViewModel.SelectConfig)
					,
					new CommandBinding(MediaCommands.Select,ViewModel.Subcommands)
					,
					new CommandBinding(ApplicationCommands.PrintPreview,ViewModel.InputPreview)
					,
					new CommandBinding(ToolboxCommands.Preview,ViewModel.InputPreview)
				});
			}
		}
	}

	namespace ViewModels
	{
		public partial class CodingModelsPageViewModel : ViewModels.FilesViewModel<Models.CodedingModelsConfig,TempletProperty>
		{
			public CodingModelsPageViewModel()
			{
				SelectFileSubcommands.Add("SourcePath", r => SourcePath = r, () => SourcePath);

				SelectPathSubcommands.Add("ModelPath", r => ModelPath = r, () => ModelPath);
				SelectPathSubcommands.Add("ViewModelPath", r => ViewModelPath = r, () => ViewModelPath);
				SelectPathSubcommands.Add("JavaPath", r => JavaPath = r, () => JavaPath);

				InputStringSubcommands.Add("ModelNamespace", r => ModelNamespace = r, () => ModelNamespace);
				InputStringSubcommands.Add("ViewModelNamespace", r => ViewModelNamespace = r, () => ViewModelNamespace);
				InputStringSubcommands.Add("JavaNamespace", r => JavaNamespace = r, () => JavaNamespace);
			}

			public void CodingModels(object sender, ExecutedRoutedEventArgs e)
			{
				InputPreview(sender, e);

				//读取输入文件
				var tpgs = from p in Items group p by p.Owner into g select g ;

				foreach (var g in tpgs)
				{
					var tps = g.ToArray();
					//转换
					var tm = new Templets.TemplateData()
					{
						DbTable = g.First().Table
					};
					tm.TempletProperties = tps;
					string s;

					//Model
					var m = new Templets.TemplateModel()
					{
						Data = tm
					};
					m.Data.Namespace = ModelNamespace;
					m.Data.Owner = g.Key + "Model";
					s = m.TransformText();
					WriteAllText(ModelPath, m.Data.Owner, s);

					//ViewModel
					var vm = new Templets.TemplateViewModel()
					{
						Data = tm
					};
					vm.Data.Namespace = ViewModelNamespace;
					m.Data.Owner = g.Key + "ViewModel";
					m.Data.ModelName = ModelNamespace + "." + g.Key + "Model";
					s = vm.TransformText();
					WriteAllText(ViewModelPath, m.Data.Owner, s);

					//Java?
				}

			}

			void _Demo(Templets.TemplateData Data)
			{
				//var r = "";
				foreach (var p in Data.TempletProperties)
				{
					if (!String.IsNullOrWhiteSpace(p.Defualt))
					{
						
					}
				}
			}

			private static void WriteAllText(string dir, string owner, string s)
			{
				var file = String.Format("{0}\\{1}.Template.cs", dir, owner);
				if (Directory.Exists(dir))
				{
				}
				else
				{
					Directory.CreateDirectory(dir);
				}
				File.WriteAllText(file, s,Encoding.UTF8);
			}

			#region 本地模型
			//生成源
			//string SourcePath;
			//string ModelNamespace;
			//string ModelPath;
			//string ViewModelNamespace;
			//string ViewModelPath;
			//string JavaNamespace;
			//string JavaPath;

			private string _sourcePath;
			public string SourcePath
			{
				get
				{
					return _sourcePath;
				}

				set
				{
					_sourcePath = value;
					OnPropertyChanged("SourcePath");
				}
			}

			private string _modelNamespace;
			public string ModelNamespace
			{
				get
				{
					return _modelNamespace;
				}

				set
				{
					_modelNamespace = value;
					OnPropertyChanged("ModelNamespace");
				}
			}

			private string _modelPath;
			public string ModelPath
			{
				get
				{
					return _modelPath;
				}

				set
				{
					_modelPath = value;
					OnPropertyChanged("ModelPath");
				}
			}

			private string _viewModelNamespace;
			public string ViewModelNamespace
			{
				get
				{
					return _viewModelNamespace;
				}

				set
				{
					_viewModelNamespace = value;
					OnPropertyChanged("ViewModelNamespace");
				}
			}

			private string _viewModelPath;
			public string ViewModelPath
			{
				get
				{
					return _viewModelPath;
				}

				set
				{
					_viewModelPath = value;
					OnPropertyChanged("ViewModelPath");
				}
			}

			private string _javaNamespace;
			public string JavaNamespace
			{
				get
				{
					return _javaNamespace;
				}

				set
				{
					_javaNamespace = value;
					OnPropertyChanged("JavaNamespace");
				}
			}

			private string _javaPath;
			public string JavaPath
			{
				get
				{
					return _javaPath;
				}

				set
				{
					_javaPath = value;
					OnPropertyChanged("JavaPath");
				}
			}

			#endregion

			protected override void LoadConfig(CodedingModelsConfig cs)
			{
				base.LoadConfig(cs);

				SourcePath = cs.SourcePath;
				ModelNamespace = cs.ModelNamespace;
				ModelPath = cs.ModelPath;
				ViewModelNamespace = cs.ViewModelNamespace;
				ViewModelPath = cs.ViewModelPath;
				JavaNamespace = cs.JavaNamespace;
				JavaPath = cs.JavaPath;

			}

			public override void SaveConfig(CodedingModelsConfig cs)
			{
				cs.SourcePath=SourcePath ;
				cs.ModelNamespace=ModelNamespace ;
				cs.ModelPath=ModelPath ;
				cs.ViewModelNamespace=ViewModelNamespace ;
				cs.ViewModelPath=ViewModelPath ;
				cs.JavaNamespace=JavaNamespace ;
				cs.JavaPath=JavaPath ;

				base.SaveConfig(cs);

			}

			internal void InputPreview(object sender, ExecutedRoutedEventArgs e)
			{

				#region 读取数据 => Items
				
				var tps = new List<TempletProperty>();
				TempletProperty tp = new TempletProperty();
				var all = ToolBox.Core.ReadXmlExcel(SourcePath);
				var tl = all[0]; 
				var tb = all.Skip(1);
				var pc = tl.Keys.Last();//表格有效列数（以标题列计算）。 // tb.Max(b => b.Max(x => x.Key)); —— 计算全空列还是会被忽略掉。

				foreach (var vs in tb)
				{
					tp.IsEnable = true;
					for (int i = 0; i <= pc; i++)
					{
						tp.SetProperty(vs, i);
					}
					var ntp = tp;
					tps.Add(ntp);
				}

				Items.UnionWith(tps);

				#endregion

			}
		}
	}

	namespace Models
	{
		public class CodedingModelsConfig : FilesConfig
		{
			public string SourcePath;
			public string ModelNamespace;
			public string ModelPath;
			public string ViewModelNamespace;
			public string ViewModelPath;
			public string JavaNamespace;
			public string JavaPath;
		}

		public struct TempletProperty
		{

			#region 属性
			//生成源
			//public string Owner;//所在类。
			//public string Table;//对应的数据库表名。
			//public string Type;//属性类型。
			//public string Name;//属性名字。
			//public string Defualt;//默认值。
			//public string Connum;//属性在数据库中的字段名。
			//public string LocalName;//显示本地语言命名。
			//public string LocalDescription;//本地语言描述。
			//public bool AutoDisplay;//是否自动呈现是出现。
			//public bool IsEnable;//本记录是否有效。

			/// <summary>
			/// 所在类
			/// </summary>
			private string _owner;//所在类。
			/// <summary>
			/// 所在类
			/// </summary>
			[Display(Name = "所在类")]
			public string Owner
			{
				get
				{
					return _owner;
				}

				set
				{
					_owner = value;
					//OnPropertyChanged("Owner");
				}
			}

			/// <summary>
			/// 对应的数据库表名
			/// </summary>
			private string _table;//对应的数据库表名。
			/// <summary>
			/// 对应的数据库表名
			/// </summary>
			[Display(Name = "对应的数据库表名")]
			public string Table
			{
				get
				{
					return _table;
				}

				set
				{
					_table = value;
					//OnPropertyChanged("Table");
				}
			}

			/// <summary>
			/// 属性类型
			/// </summary>
			private string _type;//属性类型。
			/// <summary>
			/// 属性类型
			/// </summary>
			[Display(Name = "属性类型")]
			public string Type
			{
				get
				{
					return _type;
				}

				set
				{
					_type = value;
					//OnPropertyChanged("Type");
				}
			}

			/// <summary>
			/// 属性名字
			/// </summary>
			private string _name;//属性名字。
			/// <summary>
			/// 属性名字
			/// </summary>
			[Display(Name = "属性名字")]
			public string Name
			{
				get
				{
					return _name;
				}

				set
				{
					_name = value;
					//OnPropertyChanged("Name");
				}
			}

			/// <summary>
			/// 变量名的公共成员形式
			/// </summary>
			private string _publicName;//_变量名的公共成员形式。
			/// <summary>
			/// 变量名的公共成员形式
			/// </summary>
			[Display(Name = "变量名的公共成员形式", AutoGenerateField = false)]
			public string PublicName
			{
				get
				{
					if (String.IsNullOrWhiteSpace(_publicName))
					{
						var n = this.Name;
						_publicName = n.Substring(0, 1).ToUpper() + n.Substring(1);
					}
					return _publicName;
				}

				set
				{
					_publicName = value;
					//OnPropertyChanged("PublicName");
				}
			}

			/// <summary>
			/// 变量名的私有成员形式
			/// </summary>
			private string _privateName;//_变量名的私有成员形式。
			/// <summary>
			/// 变量名的私有成员形式
			/// </summary>
			[Display(Name = "变量名的私有成员形式", AutoGenerateField = false)]
			public string PrivateName
			{
				get
				{
					if (String.IsNullOrWhiteSpace(_privateName))
					{
						_privateName = "_" + ParamName;
					}
					return _privateName;
				}

				set
				{
					_privateName = value;
					//OnPropertyChanged("PrivateName");
				}
			}

			/// <summary>
			/// 变量名的参数形式
			/// </summary>
			private string _paramName;//_变量名的参数形式。
			/// <summary>
			/// 变量名的参数形式
			/// </summary>
			[Display(Name = "变量名的参数形式", AutoGenerateField = false)]
			public string ParamName
			{
				get
				{
					if (String.IsNullOrWhiteSpace(_paramName))
					{
						var n = Name.Trim();
						while (n.StartsWith("_"))
						{
							n = n.Substring(1);
						}
						_paramName = n.Substring(0, 1).ToLower() + n.Substring(1);
					}
					return _paramName;
				}

				set
				{
					_paramName = value;
					//OnPropertyChanged("ParamName");
				}
			}

			/// <summary>
			/// 默认值
			/// </summary>
			private string _defualt;//默认值。
			/// <summary>
			/// 默认值
			/// </summary>
			[Display(Name = "默认值")]
			public string Defualt
			{
				get
				{
					return _defualt;
				}

				set
				{
					_defualt = value;
					//OnPropertyChanged("Defualt");
				}
			}

			/// <summary>
			/// 属性在数据库中的字段名
			/// </summary>
			private string _connum;//属性在数据库中的字段名。
			/// <summary>
			/// 属性在数据库中的字段名
			/// </summary>
			[Display(Name = "属性在数据库中的字段名")]
			public string Connum
			{
				get
				{
					return _connum;
				}

				set
				{
					_connum = value;
					//OnPropertyChanged("Connum");
				}
			}

			/// <summary>
			/// 显示本地语言命名
			/// </summary>
			private string _localName;//显示本地语言命名。
			/// <summary>
			/// 显示本地语言命名
			/// </summary>
			[Display(Name = "显示本地语言命名")]
			public string LocalName
			{
				get
				{
					return _localName;
				}

				set
				{
					_localName = value;
					//OnPropertyChanged("LocalName");
				}
			}

			/// <summary>
			/// 本地语言描述
			/// </summary>
			private string _localDescription;//本地语言描述。
			/// <summary>
			/// 本地语言描述
			/// </summary>
			[Display(Name = "本地语言描述")]
			public string LocalDescription
			{
				get
				{
					return _localDescription;
				}

				set
				{
					_localDescription = value;
					//OnPropertyChanged("LocalDescription");
				}
			}

			/// <summary>
			/// 是否自动呈现是出现
			/// </summary>
			private bool _autoDisplay;//是否自动呈现是出现。
			/// <summary>
			/// 是否自动呈现是出现
			/// </summary>
			[Display(Name = "是否自动呈现是出现")]
			public bool AutoDisplay
			{
				get
				{
					return _autoDisplay;
				}

				set
				{
					_autoDisplay = value;
					//OnPropertyChanged("AutoDisplay");
				}
			}

			/// <summary>
			/// 本记录是否有效
			/// </summary>
			private bool _isEnable;//本记录是否有效。
			/// <summary>
			/// 本记录是否有效
			/// </summary>
			[Display(Name = "本记录是否有效")]
			public bool IsEnable
			{
				get
				{
					return _isEnable;
				}

				set
				{
					_isEnable = value;
					//OnPropertyChanged("IsEnable");
				}
			}


			
			#endregion

			public override string ToString()
			{
				return string.Format("{0}.{1}", Owner,Name);
			}
			public void SetProperty(IDictionary<int, string> vs, int idx)
			{
				if (vs.ContainsKey(idx))
				{
					var v = vs[idx];
					if (String.IsNullOrEmpty(vs[idx]))
					{
						SetPropertyAsEmpty(idx);
					}
					else
					{
						switch (idx)
						{
							case 0:
								Owner = v;
								break;
							case 1:
								Table = v;
								break;
							case 2:
								Type = v;
								break;
							case 3:
								Name = v;
								break;
							case 4:
								Defualt = v;
								break;
							case 5:
								Connum = v;
								break;
							case 6:
								LocalName = v.EndsWith("。")?v.Substring(0,v.Length-1):v;
								break;
							case 7:
								LocalDescription = v.EndsWith("。") ? v: v+"。";
								break;
							case 8:
								AutoDisplay = v!="0";
								break;
							default:
								throw new Exception("未知属性！");
								//break;
						}
					}
				}
				else
				{
					SetPropertyAsEmpty(idx);
				}
			}

			/// <summary>
			/// 处理对应列不存在或者值为空的情况。
			/// </summary>
			/// <param name="idx"></param>
			private void SetPropertyAsEmpty(int idx)
			{
				switch (idx)
				{
					case 2:
					case 3:
						IsEnable = false;
						break;
					case 4:
						Defualt = null;
						break;
					case 6:
						LocalName = null;
						break;
					case 7:
						LocalDescription = LocalName+"。";
						break;
					case 8:
						AutoDisplay = true;
						break;
				}
			}

			public string GetDisplay()
			{
				var p = this;
				var hasDescription = !String.IsNullOrWhiteSpace(p.LocalDescription);
				var hasName = !String.IsNullOrWhiteSpace(p.LocalName);
				var hasDisplay = hasName || hasDescription || !p.AutoDisplay;
				
				var sb = new StringBuilder();

				if (hasDisplay)
				{
					sb.Append("[Display(");
					var ps = new List<string>();

					if (hasName)
					{
						ps.Add("Name=\"" + p.LocalName + "\"");
					}

					if (hasDescription)
					{
						ps.Add("Description=\"" + p.LocalDescription + "\"");
					}

					if (!p.AutoDisplay)
					{
						ps.Add("AutoGenerateField = false");
					}

					sb.Append(String.Join(",", ps.ToArray()));
					sb.Append(")]");
				}

				return sb.ToString();
			}
		}
	}


}
